<template>
  <div
    class="qr-code"
    v-loading="loading"
    :style="{
      width: `${width}px`,
      height: `${height}px`,
      padding: `${padding}px`
    }"
  >
    <div class="qr-error login-tips" v-if="!hasLogin">
      <el-button size="small" type="primary" @click="$emit('login')">
        <span>请先登录</span>
      </el-button>
    </div>
    <div class="code-box" v-show="hasLogin">
      <!-- <div
        ref="qrCode"
        key="code">
      </div> -->
      <div class="qrcode" ref="qrcode" v-show="!error" v-loading="loading">
        <img :src="qrCodeImg" />
      </div>
      <div
        v-show="error || confirmTips"
        class="refresh qr-error"
        key="refresh"
        @click="refreshCode"
      >
        <div v-if="error">
          <svg-icon icon-class="code-refresh" />
          <p class="text-error">{{ error }}</p>
        </div>
        <div class="confirm-tips" v-else v-html="confirmTips" />
      </div>
    </div>
  </div>
</template>
<script lang="ts">
import { getParams, debounce } from "@/utils";
// @ts-ignore
import QRCode from "qrcodejs2-fix";
// @ts-ignore
import { getPrepayCode, checkCodeStatus, checkCodeFinish } from "./api";
import alipaySvg from "./alipay.svg";
// @ts-ignore
export default {
  name: "PaymentCode",
  emits: ["login", "refresh", "onStatusChange"],
  props: {
    hasLogin: {
      type: Boolean,
      default: false
    },
    product: {
      type: Object,
      require: true
    },
    otherParamsStr: {
      type: String,
      default: "{}"
    },
    width: {
      type: Number,
      default: 150
    },
    height: {
      type: Number,
      default: 150
    },
    padding: {
      type: Number,
      default: 10
    }
  },
  data() {
    return {
      isOnShow: true,
      loading: false,
      qrcode: null,
      timer: null,
      validMinute: "10",
      error: "",
      confirmTips: "",
      times: 600,
      qrCodeImg: ""
    };
  },
  watch: {
    "product.id": {
      handler() {
        if (this.getPrepayCodeInfo_) {
          this.getPrepayCodeInfo_();
        } else {
          this.getPrepayCodeInfo();
        }
      },
      immediate: true
    },
    otherParamsStr() {
      this.getPrepayCodeInfo_();
    },
    hasLogin() {
      this.getPrepayCodeInfo_();
    }
  },
  created() {
    this.getPrepayCodeInfo_ = debounce(
      () => {
        this.getPrepayCodeInfo();
      },
      250,
      false
    );
  },
  mounted() {
    // const container = this.$refs.qrCode
    // this.qrcode = new QRCode(container, {
    //   text: this.text,
    //   width: this.width - this.padding * 2,
    //   height: this.height - this.padding * 2,
    //   colorDark: '#000000',
    //   colorLight: '#ffffff',
    //   correctLevel: 0
    // })
  },
  activated() {
    this.isOnShow = true;
    this.getPrepayCodeInfo();
  },
  deactivated() {
    this.isOnShow = false;
    this.getPrepayCodeInfo();
  },
  beforeUnmount() {
    this.isOnShow = false;
    this.getPrepayCodeInfo();
  },
  methods: {
    refreshCode() {
      this.$emit("refresh");
      this.getPrepayCodeInfo();
    },
    getInstance(w: number|string, h: number|string) {
      if (this.instance) return this.instance;
      const div = document.createElement("div");
      this.instance = new QRCode(div, {
        text: "",
        render: "canvas",
        width: w,
        height: h,
        colorDark: "#000000",
        colorLight: "#ffffff",
        correctLevel: QRCode.CorrectLevel.Q
      });
      return this.instance;
    },
    setQrcode(url: string) {
      const h = this.width - this.padding * 2;
      const w = this.height - this.padding * 2;
      const instance = this.getInstance(h, w);
      instance.makeCode(url);
      const canvas = instance._oDrawing._elCanvas;
      if (this.product.cycle_pay_flag) {
        const ctx = canvas.getContext("2d");
        const image = new Image();
        image.src = alipaySvg;
        image.onload = () => {
          const imgW = this.width < 150 ? 24 : 28;
          const imgH = this.height < 150 ? 24 : 28;
          const padding = 1;
          const bgw = imgW + padding * 2;
          const bgh = imgH + padding * 2;
          const bgx = (w - bgw) / 2;
          const bgy = (h - bgh) / 2;
          // 画logo后面白色背景图
          this.drawArcBackground(ctx, bgx, bgy, bgw, bgh, 0);

          // 画logo
          const logx = (w - imgW) / 2;
          const logy = (h - imgH) / 2;
          ctx.drawImage(image, logx, logy, imgW, imgH);
          this.loading = false;
          this.qrCodeImg = canvas.toDataURL("image/png");
        };
      } else {
        this.loading = false;
        this.qrCodeImg = canvas.toDataURL("image/png");
      }
    },
    // 画正方形背景
    drawArcBackground(ctx: CanvasRenderingContext2D, x: number, y: number, w: number, h: number, r: number) {
      ctx.beginPath();
      ctx.moveTo(x + r, y);
      ctx.lineTo(x + w - r, y);
      ctx.arc(x + w - r, y + r, r, Math.PI * 1.5, Math.PI * 2);
      ctx.lineTo(x + w, y + h - r);
      ctx.arc(x + w - r, y + h - r, r, 0, Math.PI * 0.5);
      ctx.lineTo(x + r, y + h);
      ctx.arc(x + r, y + h - r, r, Math.PI * 0.5, Math.PI);
      ctx.lineTo(x, y + r);
      ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5);
      ctx.closePath();

      ctx.fillStyle = "#fff";
      ctx.fill();
    },
    setTime(oldCode: string) {
      clearTimeout(this.timer);
      this.timer = setTimeout(() => {
        if (!this.qrCode || this.error || oldCode !== this.qrCode) return;
        oldCode = this.qrCode;
        checkCodeStatus({ qr_code: this.qrCode })
          .then((res: any) => {
            if (oldCode !== this.qrCode) return;
            const data = res.data || {};
            if (data.expire < 1) {
              this.error = "支付超时!";
              this.$emit("onStatusChange", "timeout");
            } else if (data.status === 1) {
              this.confirmTips = "已扫码<br/>如果出现问题<br/>请刷新当前页面";
            } else if (data.status === 0) {
              this.getPrepayCodeInfo();
              this.$emit("onStatusChange", "succes");
            } else if (data.status === 2) {
              this.error = "订单无效!";
              this.$emit("onStatusChange", "error");
            }
            this.setTime(oldCode);
          })
          .catch(() => {
            if (this.times <= 0) {
              this.error = "二维码已过期";
            } else {
              this.setTime(oldCode);
            }
            this.times -= 3;
          });
      }, 3000);
    },
    getPrepayCodeInfo() {
      clearTimeout(this.timer);
      this.qrCode = null;
      this.confirmTips = "";
      if ([!this.isOnShow, !this.hasLogin, !this.product.id].includes(true))
        return;
      // if (!this.isOnShow || !this.hasLogin || !this.product.id) return
      const params = { pay_entry: "web" };
      this.loading = true;
      getPrepayCode(params)
        .then((res: any) => {
          this.loading = false;
          this.error = "";
          const data = res.data;
          this.qrCode = data.qr_code;
          this.makePayCode();
          this.validMinute = data.valid_minute || 10;
          this.times = data.poll_second || 600;
          this.setTime(this.qrCode);
        })
        .catch(() => {
          this.error = "请刷新二维码";
          this.loading = false;
        });
    },
    makePayCode() {
      // if (this.qrcode) {
      const otherParams = JSON.parse(this.otherParamsStr || "{}");
      const params = Object.assign(
        {
          product: this.product.id,
          codeid: this.qrCode,
          appname: "translate",
          wxid: import.meta.env.VITE_APP_WXPAY_ID,
          appid: import.meta.env.VITE_APP_MERCHANTID,
          ...(import.meta.env.VITE_APP_ALIPAY_ID
            ? {
                aliid: import.meta.env.VITE_APP_ALIPAY_ID
              }
            : {})
        },
        otherParams
      );

      if (params.noproduct) {
        delete params.noproduct;
        delete params.product;
      }
      const paramsStr = getParams(params);
      this.setQrcode(
        `https://${import.meta.env.VITE_APP_H5_PAY_ORIGIN}/pay.html?${paramsStr}`
      );
      // this.qrcode.makeCode('https://usercenter-pay.xiangtatech.com/pay.html?' + paramsStr)
      //   this.qrcode._el.title = ''
      // }
    },
    hasPay() {
      if (!this.qrCode) return;
      checkCodeFinish({ qr_code: this.qrCode }).then(() => {
        this.getPrepayCodeInfo();
        this.$emit("onStatusChange", "succes");
      });
    }
  }
};
</script>
<style lang="scss" scoped>
@import "./index.scss";
</style>
